
<template>
  <transition name="pt-message-fade" @after-leave="handleAfterLeave">
    <div
      :class="[
        'pt-message',
        'pt-message',
        type && !iconClass ? `pt-message--${ type }` : '',
        center ? 'is-center' : '',
        showClose ? 'is-closable' : '',
        customClass
      ]"
      :style="positionStyle"
      v-show="visible"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
      role="alert"
    >
      <i :class="iconClass" v-if="iconClass"></i>
      <i :class="typeClass" v-else></i>
      <slot>
        <p v-if="!dangerouslyUseHTMLString" class="pt-message__content">{{ message }}</p>
        <p v-else v-html="message" class="pt-message__content"></p>
      </slot>
      <i v-if="showClose" class="pt-message__closeBtn pt-icon-close" @click="close"></i>
    </div>
  </transition>
</template>

<script type="text/babel">
const typeMap = {
  success: "success",
  info: "info",
  warning: "warning",
  error: "error"
};

export default {
  name: "Ptmessage",
  data () {
    return {
      visible: true,
      message: "",
      duration: 3000,
      type: "info",
      iconClass: "",
      customClass: "",
      onClose: null,
      showClose: false,
      closed: false,
      verticalOffset: 20,
      timer: null,
      dangerouslyUseHTMLString: false,
      center: false
    };
  },

  computed: {
    typeClass () {
      return this.type && !this.iconClass ?
        `pt-message__icon pt-icon-${typeMap[this.type]}` :
        "";
    },
    positionStyle () {
      return {
        "top": `${this.verticalOffset}px`
      };
    }
  },

  watch: {
    closed (newVal) {
      if (newVal) {
        this.visible = false;
      }
    }
  },

  methods: {
    handleAfterLeave () {
      this.$destroy(true);
      this.$el.parentNode.removeChild(this.$el);
    },

    close () {
      this.closed = true;
      if (typeof this.onClose === "function") {
        this.onClose(this);
      }
    },

    clearTimer () {
      clearTimeout(this.timer);
    },

    startTimer () {
      if (this.duration > 0) {
        this.timer = setTimeout(() => {
          if (!this.closed) {
            this.close();
          }
        }, this.duration);
      }
    },
    keydown (e) {
      if (e.keyCode === 27) { // esc关闭消息
        if (!this.closed) {
          this.close();
        }
      }
    }
  },
  mounted () {
    this.startTimer();
    document.addEventListener("keydown", this.keydown);
  },
  beforeDestroy () {
    document.removeEventListener("keydown", this.keydown);
  }
};
</script>

<style lang="less" scoped>
.pt-message__closeBtn:focus,
.pt-message__content:focus {
  outline-width: 0;
}
.pt-message {
  position: fixed;
  left: 50%;
  top: 20px;
  display: flex;
  align-items: center;
  padding: 15px 15px 15px 20px;
  border-radius: 4px;
  border: 1px solid #ebeef5;
  min-width: 380px;
  transform: translateX(-50%);
  transition: opacity 0.3s, transform 0.4s, top 0.4s;
  background-color: #edf2fc;
  overflow: hidden;
  z-index: 1999;
  &.is-center {
    justify-content: center;
  }
  &.is-closable {
    .pt-message__content {
      padding-right: 16px;
    }
  }
  p {
    margin: 0;
  }
  .pt-icon-success {
    color: #67c23a;
  }
  .pt-icon-error {
    color: #f56c6c;
  }
  .pt-icon-info {
    color: #909399;
  }
  .pt-icon-warning {
    color: #e6a23c;
  }
}
.pt-message--info {
  .pt-message__content {
    color: #909399;
  }
}
.pt-message--success {
  background-color: #f0f9eb;
  border-color: #e1f3d8;
  .pt-message__content {
    color: #67c23a;
  }
}
.pt-message--warning {
  background-color: #fdf6ec;
  border-color: #faecd8;
  .pt-message__content {
    color: #e6a23c;
  }
}
.pt-message--error {
  background-color: #fef0f0;
  border-color: #fde2e2;
  .pt-message__content {
    color: #f56c6c;
  }
}
.pt-message__icon {
  margin-right: 10px;
}
.pt-message__content {
  padding: 0;
  font-size: 14px;
  line-height: 1;
}
.pt-message__closeBtn {
  position: absolute;
  top: 50%;
  right: 15px;
  transform: translateY(-50%);
  cursor: pointer;
  color: #c0c4cc;
  font-size: 16px;
  &:hover {
    color: #909399;
  }
}
.pt-message-fade-enter,
.pt-message-fade-leave-active {
  opacity: 0;
  transform: translate(-50%, -100%);
}
</style>
